package com.zshan.clinic.admin.service.clinic;

import com.zshan.clinic.admin.constant.Constants;
import com.zshan.clinic.admin.entity.vo.ClinicDeptSelectVo;
import com.zshan.clinic.admin.entity.vo.ClinicDeptVo;
import com.zshan.clinic.admin.entity.vo.ClinicRoomVo;
import com.zshan.clinic.admin.mapper.clinic.SpecClinicDeptMapper;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.enums.YesOrNoEnum;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.page.PageInfo;
import com.zshan.clinic.common.util.page.PageUtils;
import com.zshan.clinic.common.util.string.StringUtil;
import com.zshan.clinic.database.dao.ClinicDeptMapper;
import com.zshan.clinic.database.dao.ClinicDeptRoomMapper;
import com.zshan.clinic.database.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 诊所科室
 */
@Service
@Slf4j
public class ClinicDeptService {

    @Autowired
    private ClinicDeptMapper clinicDeptMapper;

    @Autowired
    private ClinicDeptRoomMapper clinicDeptRoomMapper;

    @Autowired
    private SpecClinicDeptMapper specClinicDeptMapper;

    @Autowired
    @Lazy
    private ClinicEmpService clinicEmpService;


    /**
     * 获取诊所的科室下拉框数据
     * @param clinicId
     * @return
     */
    public List<ClinicDeptSelectVo> getSelectList(Long clinicId){
        List<ClinicDept> deptList = getDeptListByClinicId(clinicId);
        if(CollectionUtils.isEmpty(deptList)){
            return Collections.EMPTY_LIST;
        }
        // 将实体列表转换为DTO列表
        return deptList.stream().map(dept -> {
            ClinicDeptSelectVo selectVo = new ClinicDeptSelectVo();
            BeanUtils.copyProperties(dept, selectVo);
            return selectVo;
        }).collect(Collectors.toList());
    }

    /**
     * 查询诊所的科室
     * @param clinicId
     * @return
     */
    public List<ClinicDept> getDeptListByClinicId(Long clinicId) {
        ClinicDeptExample example = new ClinicDeptExample();
        ClinicDeptExample.Criteria criteria = example.createCriteria();
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andIsEnabledEqualTo(YesOrNoEnum.YES.getValue());
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return clinicDeptMapper.selectByExample(example);
    }

    /**
     * 查询诊室列表
     * @param clinicId
     * @param roomName
     * @return
     */
    public PageInfo<ClinicRoomVo> getRoomList(Long clinicId,Long deptId,String roomName, Integer pageNo, Integer pageSize){
        Long totalCount = specClinicDeptMapper.getRoomCount(clinicId,deptId,roomName);
        if(StringUtil.isBlank(totalCount)){
            return PageInfo.build();
        }
        List<ClinicRoomVo> roomList = specClinicDeptMapper.getRoomList(clinicId,deptId,roomName, PageUtils.getOffset(pageNo,pageSize),pageSize);
        return new PageInfo<>(totalCount,roomList);
    }

    /**
     * 添加
     * @param clinicDeptRoom
     */
    @Transactional(rollbackFor = Exception.class)
    public void addRoom(ClinicDeptRoom clinicDeptRoom) {
        validateClinicDeptRoom(clinicDeptRoom);
        clinicDeptRoom.setIsDelete(YesOrNoEnum.NO.getValue());
        clinicDeptRoom.setIsEnabled(YesOrNoEnum.YES.getValue());
        clinicDeptRoom.setCreateTime(new Date());
        clinicDeptRoomMapper.insertSelective(clinicDeptRoom);
    }

    public void validateClinicDeptRoom(ClinicDeptRoom clinicDeptRoom) {
        clinicDeptRoom.setRoomName(StringUtil.removeAllWhitespace(clinicDeptRoom.getRoomName()));
        if(StringUtil.isBlank(clinicDeptRoom.getRoomName())){
            throw new BusinessFailException("诊室名不能为空");
        }
        if(clinicDeptRoom.getRoomName().length() > Constants.ROOM_LENGTH){
            throw new BusinessFailException("诊室名"+ Constants.ROOM_LENGTH+"字以内！");
        }
        Long roomCount = getRoomCountByName(clinicDeptRoom.getClinicId(),clinicDeptRoom.getRoomId(),clinicDeptRoom.getRoomName());
        if(roomCount > CommonConstant.DEFAULT_0){
            throw new BusinessFailException("诊室名不能重复！");
        }
        ClinicDept clinicDept = getEnabledClinicDeptById(clinicDeptRoom.getDeptId());
        if(clinicDept == null || !clinicDeptRoom.getClinicId().equals(clinicDept.getClinicId())){
            throw new BusinessFailException("科室不存在");
        }
    }

    private Long getRoomCountByName(Long clinicId, Long roomId, String roomName) {
        ClinicDeptRoomExample example = new ClinicDeptRoomExample();
        ClinicDeptRoomExample.Criteria criteria = example.createCriteria();
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andRoomNameEqualTo(roomName);
        if(!StringUtil.isBlank(roomId)){
            criteria.andRoomIdNotEqualTo(roomId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return clinicDeptRoomMapper.countByExample(example);
    }

    /**
     * 根据ID查询启用状态的诊室
     * @param roomId
     * @return
     */
    public ClinicDeptRoom getEnabledClinicRoomById(Long roomId){
        ClinicDeptRoom clinicDeptRoom = getClinicDeptRoomById(roomId);
        if(clinicDeptRoom == null){
            return null;
        }
        if(YesOrNoEnum.NO.getValue().equals(clinicDeptRoom.getIsEnabled())){
            return null;
        }
        return clinicDeptRoom;
    }

    /**
     * 根据ID查询诊室信息
     * @param roomId
     * @return
     */
    public ClinicDeptRoom getClinicDeptRoomById(Long roomId){
        if(StringUtil.isBlank(roomId)){
            return null;
        }
        ClinicDeptRoom clinicDeptRoom = clinicDeptRoomMapper.selectByPrimaryKey(roomId);
        if(clinicDeptRoom == null || YesOrNoEnum.YES.getValue().equals(clinicDeptRoom.getIsDelete())){
            return null;
        }
        return clinicDeptRoom;
    }


    /**
     * 修改
     * @param clinicDeptRoom
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRoom(ClinicDeptRoom clinicDeptRoom) {
        validateClinicDeptRoom(clinicDeptRoom);
        ClinicDeptRoom dbClinicDeptRoom = getClinicDeptRoomById(clinicDeptRoom.getRoomId());
        if(dbClinicDeptRoom == null){
            throw new BusinessFailException("诊室不存在");
        }
        clinicDeptRoom.setUpdateTime(new Date());
        clinicDeptRoomMapper.updateByPrimaryKeySelective(clinicDeptRoom);
    }


    /**
     * 删除
     * @param clinicDeptRoom
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoom(ClinicDeptRoom clinicDeptRoom) {
        ClinicDeptRoom dbClinicDeptRoom = getClinicDeptRoomById(clinicDeptRoom.getRoomId());
        if(dbClinicDeptRoom == null){
            throw new BusinessFailException("诊室不存在");
        }
        dbClinicDeptRoom.setIsDelete(YesOrNoEnum.YES.getValue());
        dbClinicDeptRoom.setUpdateUserId(clinicDeptRoom.getUpdateUserId());
        dbClinicDeptRoom.setUpdateBy(clinicDeptRoom.getUpdateBy());
        dbClinicDeptRoom.setUpdateTime(new Date());
        clinicDeptRoomMapper.updateByPrimaryKeySelective(dbClinicDeptRoom);
    }

    /**
     * 启用诊室
     * @param clinicDeptRoom
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableRoom(ClinicDeptRoom clinicDeptRoom) {
        ClinicDeptRoom dbClinicDeptRoom = getClinicDeptRoomById(clinicDeptRoom.getRoomId());
        if(dbClinicDeptRoom == null){
            throw new BusinessFailException("诊室不存在");
        }
        if(YesOrNoEnum.YES.getValue().equals(dbClinicDeptRoom.getIsEnabled())){
            return;
        }
        dbClinicDeptRoom.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbClinicDeptRoom.setUpdateUserId(clinicDeptRoom.getUpdateUserId());
        dbClinicDeptRoom.setUpdateBy(clinicDeptRoom.getUpdateBy());
        dbClinicDeptRoom.setUpdateTime(new Date());
        clinicDeptRoomMapper.updateByPrimaryKeySelective(dbClinicDeptRoom);
    }

    /**
     * 停用诊室
     * @param clinicDeptRoom
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableRoom(ClinicDeptRoom clinicDeptRoom) {
        ClinicDeptRoom dbClinicDeptRoom = getClinicDeptRoomById(clinicDeptRoom.getRoomId());
        if(dbClinicDeptRoom == null){
            throw new BusinessFailException("诊室不存在");
        }
        if(YesOrNoEnum.NO.getValue().equals(dbClinicDeptRoom.getIsEnabled())){
            return;
        }
        dbClinicDeptRoom.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbClinicDeptRoom.setUpdateUserId(clinicDeptRoom.getUpdateUserId());
        dbClinicDeptRoom.setUpdateBy(clinicDeptRoom.getUpdateBy());
        dbClinicDeptRoom.setUpdateTime(new Date());
        clinicDeptRoomMapper.updateByPrimaryKeySelective(dbClinicDeptRoom);
    }


    /**
     * 查询诊室列表
     * @param clinicId
     * @param deptName
     * @return
     */
    public PageInfo<ClinicDeptVo> getDeptList(Long clinicId, String deptName, Integer pageNo, Integer pageSize){
        Long totalCount = specClinicDeptMapper.getDeptCount(clinicId,deptName);
        if(StringUtil.isBlank(totalCount)){
            return PageInfo.build();
        }
        List<ClinicDeptVo> deptList = specClinicDeptMapper.getDeptList(clinicId,deptName, PageUtils.getOffset(pageNo,pageSize),pageSize);
        return new PageInfo<>(totalCount,deptList);
    }

    /**
     * 添加
     * @param clinicDept
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDept(ClinicDept clinicDept) {
        validateClinicDept(clinicDept);
        clinicDept.setIsDelete(YesOrNoEnum.NO.getValue());
        clinicDept.setIsEnabled(YesOrNoEnum.YES.getValue());
        clinicDept.setCreateTime(new Date());
        clinicDeptMapper.insertSelective(clinicDept);
    }

    /**
     * 科室名重复性校验
     * @param clinicId
     * @param deptId
     * @param deptName
     * @return
     */
    public Long getDeptCountByName(Long clinicId,Long deptId,String deptName){
        ClinicDeptExample example = new ClinicDeptExample();
        ClinicDeptExample.Criteria criteria = example.createCriteria();
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andDeptNameEqualTo(deptName);
        if(!StringUtil.isBlank(deptId)){
            criteria.andDeptIdNotEqualTo(deptId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        return clinicDeptMapper.countByExample(example);
    }

    public void validateClinicDept(ClinicDept clinicDept) {
        clinicDept.setDeptName(StringUtil.removeAllWhitespace(clinicDept.getDeptName()));
        if(StringUtil.isBlank(clinicDept.getDeptName())){
            throw new BusinessFailException("科室名不能为空");
        }
        if(clinicDept.getDeptName().length() > Constants.DEPT_LENGTH){
            throw new BusinessFailException("科室名"+ Constants.DEPT_LENGTH+"字以内！");
        }
        Long deptCount = getDeptCountByName(clinicDept.getClinicId(),clinicDept.getDeptId(),clinicDept.getDeptName());
        if(deptCount > CommonConstant.DEFAULT_0){
            throw new BusinessFailException("科室名不能重复！");
        }
        if(StringUtil.isBlank(clinicDept.getIsReg())){
            clinicDept.setIsReg(YesOrNoEnum.NO.getValue());
        }
        if(!StringUtil.isBlank(clinicDept.getDirectorId())){
            ClinicEmp clinicEmp = clinicEmpService.getEnabledEmpById(clinicDept.getDirectorId());
            if(clinicEmp == null || !clinicDept.getClinicId().equals(clinicEmp.getClinicId())){
                throw new BusinessFailException("负责人不存在");
            }
        }
        clinicDept.setEmpCount(CommonConstant.DEFAULT_0);
    }

    /**
     * 根据ID查询科室信息
     * @param deptId
     * @return
     */
    public ClinicDept getClinicDeptById(Long deptId){
        if(StringUtil.isBlank(deptId)){
            return null;
        }
        ClinicDept clinicDept = clinicDeptMapper.selectByPrimaryKey(deptId);
        if(clinicDept == null || YesOrNoEnum.YES.getValue().equals(clinicDept.getIsDelete())){
            return null;
        }
        return clinicDept;
    }


    /**
     * 根据ID查询启用状态的科室
     * @param deptId
     * @return
     */
    public ClinicDept getEnabledClinicDeptById(Long deptId){
        ClinicDept clinicDept = getClinicDeptById(deptId);
        if(clinicDept == null){
            return null;
        }
        if(YesOrNoEnum.NO.getValue().equals(clinicDept.getIsEnabled())){
            return null;
        }
        return clinicDept;
    }


    /**
     * 修改
     * @param clinicDept
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateDept(ClinicDept clinicDept) {
        validateClinicDept(clinicDept);
        ClinicDept dbClinicDept = getClinicDeptById(clinicDept.getDeptId());
        if(dbClinicDept == null){
            throw new BusinessFailException("科室不存在");
        }
        updateByPrimaryKeySelective(clinicDept);
    }

    /**
     * 修改科室信息
     * @param clinicDept
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateByPrimaryKeySelective(ClinicDept clinicDept) {
        clinicDept.setUpdateTime(new Date());
        clinicDeptMapper.updateByPrimaryKeySelective(clinicDept);
    }


    /**
     * 删除
     * @param clinicDept
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteDept(ClinicDept clinicDept) {
        ClinicDept dbClinicDept = getClinicDeptById(clinicDept.getDeptId());
        if(dbClinicDept == null){
            throw new BusinessFailException("科室不存在");
        }
        if(dbClinicDept.getEmpCount() > CommonConstant.DEFAULT_0){
            throw new BusinessFailException("当前科室下已关联员工，请移除后再试！");
        }
        dbClinicDept.setIsDelete(YesOrNoEnum.YES.getValue());
        dbClinicDept.setUpdateUserId(clinicDept.getUpdateUserId());
        dbClinicDept.setUpdateBy(clinicDept.getUpdateBy());
        dbClinicDept.setUpdateTime(new Date());
        clinicDeptMapper.updateByPrimaryKeySelective(dbClinicDept);
    }

    /**
     * 启用科室
     * @param clinicDept
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableDept(ClinicDept clinicDept) {
        ClinicDept dbClinicDept = getClinicDeptById(clinicDept.getDeptId());
        if(dbClinicDept == null){
            throw new BusinessFailException("科室不存在");
        }
        if(YesOrNoEnum.YES.getValue().equals(dbClinicDept.getIsEnabled())){
            return;
        }
        dbClinicDept.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbClinicDept.setUpdateUserId(clinicDept.getUpdateUserId());
        dbClinicDept.setUpdateBy(clinicDept.getUpdateBy());
        dbClinicDept.setUpdateTime(new Date());
        clinicDeptMapper.updateByPrimaryKeySelective(dbClinicDept);
    }

    /**
     * 停用科室
     * @param clinicDept
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableDept(ClinicDept clinicDept) {
        ClinicDept dbClinicDept = getClinicDeptById(clinicDept.getDeptId());
        if(dbClinicDept == null){
            throw new BusinessFailException("科室不存在");
        }
        if(YesOrNoEnum.NO.getValue().equals(dbClinicDept.getIsEnabled())){
            return;
        }
        if(dbClinicDept.getEmpCount() > CommonConstant.DEFAULT_0){
            throw new BusinessFailException("当前科室下已关联员工，请移除后再试！");
        }
        dbClinicDept.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbClinicDept.setUpdateUserId(clinicDept.getUpdateUserId());
        dbClinicDept.setUpdateBy(clinicDept.getUpdateBy());
        dbClinicDept.setUpdateTime(new Date());
        clinicDeptMapper.updateByPrimaryKeySelective(dbClinicDept);
    }

    public List<ClinicDept> getEnabledClinicDeptByIds(Long clinicId,List<Long> deptIds) {
        if(CollectionUtils.isEmpty(deptIds)){
            return Collections.EMPTY_LIST;
        }
        ClinicDeptExample example = new ClinicDeptExample();
        ClinicDeptExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        criteria.andIsEnabledEqualTo(YesOrNoEnum.YES.getValue());
        criteria.andDeptIdIn(deptIds);
        criteria.andClinicIdEqualTo(clinicId);
        return clinicDeptMapper.selectByExample(example);
    }

    public List<ClinicDeptRoom> getEnabledClinicRoomByIds(Long clinicId,List<Long> roomIds) {
        if(CollectionUtils.isEmpty(roomIds)){
            return Collections.EMPTY_LIST;
        }
        ClinicDeptRoomExample example = new ClinicDeptRoomExample();
        ClinicDeptRoomExample.Criteria criteria = example.createCriteria();
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        criteria.andIsEnabledEqualTo(YesOrNoEnum.YES.getValue());
        criteria.andRoomIdIn(roomIds);
        criteria.andClinicIdEqualTo(clinicId);
        return clinicDeptRoomMapper.selectByExample(example);
    }
}
